package com.linzm.leetcode.primary.exercises4_20230129;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * @Author zimingl
 * @Date 2023/2/2 23:25
 * @Description: 最长和谐子序列
 * 和谐数组是指一个数组里元素的最大值和最小值之间的差别 正好是 1 。
 * 现在，给你一个整数数组 nums ，请你在所有可能的子序列中找到最长的和谐子序列的长度。
 * 数组的子序列是一个由数组派生出来的序列，它可以通过删除一些元素或不删除元素、且不改变其余元素的顺序而得到。
 * 输入：nums = [1,3,2,2,5,2,3,7]
 * 输出：5
 * 解释：最长的和谐子序列是 [3,2,2,2,3]
 * 1 <= nums.length <= 2 * 104
 * -109 <= nums[i] <= 109
 */
public class Demo8_594 {
    public static void main(String[] args) {
        int[] nums = {1,3,2,2,5,2,3,7};
//        int[] nums = {1,1,2,2};
        Demo8_594 demo8_594 = new Demo8_594();
        int lhs = demo8_594.findLHS2(nums);
        System.out.println(lhs);
    }

    private int findLHS(int[] nums) {
        int count = 0;
        TreeMap<Integer, Integer> map = new TreeMap<>();
        for (int i = 0; i < nums.length; i++) {
            map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
        }
        if (map.size() == 1) {
            return 0;
        }
        List<Integer> list = map.keySet().stream().sorted().collect(Collectors.toList());
        for (int i = 0; i < list.size() - 1; i++) {
            if (list.get(i + 1) - list.get(i) == 1) {
                count = Math.max(count, map.get(list.get(i)) + map.get(list.get(i + 1)));
            }
        }
        return count;
    }

    public int findLHS2(int[] nums) {
        HashMap<Integer, Integer> cnt = new HashMap <>();
        int res = 0;
        for (int num : nums) {
            cnt.put(num, cnt.getOrDefault(num, 0) + 1);
        }
        for (int key : cnt.keySet()) {
            if (cnt.containsKey(key + 1)) {
                res = Math.max(res, cnt.get(key) + cnt.get(key + 1));
            }
        }
        return res;
    }

    public int findLHS3(int[] nums) {
        Arrays.sort(nums);
        int begin = 0;
        int res = 0;
        for (int end = 0; end < nums.length; end++) {
            while (nums[end] - nums[begin] > 1) {
                begin++;
            }
            if (nums[end] - nums[begin] == 1) {
                res = Math.max(res, end - begin + 1);
            }
        }
        return res;
    }
}
